﻿(function(){
	// base64 encoder/decoder
	var b64 = {};
	(function(ns) {
	    var keyStr = "ABCDEFGHIJKLMNOP" +
	       "QRSTUVWXYZabcdef" +
	       "ghijklmnopqrstuv" +
	       "wxyz0123456789+/" +
	       "=";
	    keyStr = "■＾＠▲☆※→←◇↑↓〓￣＿◆□" +
	    	"§★△○◎＼№＆●#㈠⑸⑶㈢⒊㈣" +
	    	"㈤㈥⒏㈦㈧㈨⑺⑹⒐⒑⒈⒋㈡⒌⒎⑷" +
	    	"⒉⑵⒍⑴ˉ，、；：？！…—·¨｝" +
	    	"л";

	    ns.encode = function(input) {
	    	input = escape(input);
	        var output = "";
	        var chr1, chr2, chr3 = "";
	        var enc1, enc2, enc3, enc4 = "";
	        var i = 0;

	        do {
	            chr1 = input.charCodeAt(i++);
	            chr2 = input.charCodeAt(i++);
	            chr3 = input.charCodeAt(i++);

	            enc1 = chr1 >> 2;
	            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
	            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
	            enc4 = chr3 & 63;

	            if (isNaN(chr2)) {
	                enc3 = enc4 = 64;
	            } else if (isNaN(chr3)) {
	                enc4 = 64;
	            }

	            output = output +
	               keyStr.charAt(enc1) +
	               keyStr.charAt(enc2) +
	               keyStr.charAt(enc3) +
	               keyStr.charAt(enc4);
	            chr1 = chr2 = chr3 = "";
	            enc1 = enc2 = enc3 = enc4 = "";
	        } while (i < input.length);

	        return output;
	    }

	    ns.decode = function(input) {
	        var output = "";
	        var chr1, chr2, chr3 = "";
	        var enc1, enc2, enc3, enc4 = "";
	        var i = 0;

	        // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
	        var base64test = /[^A-Za-z0-9\+\/\=]/g;
	        base64test = new RegExp("[^" + keyStr.split("").join("|") + "]", "g");
	        if (base64test.exec(input)) {
	            throw new Error("There were invalid base64 characters in the input text.\n" +
			      "Valid base64 characters are" + base64test.toString() + "\n" +
			      "Expect errors in decoding.");
	        }
	        input = input.replace(base64test, "");

	        do {
	            enc1 = keyStr.indexOf(input.charAt(i++));
	            enc2 = keyStr.indexOf(input.charAt(i++));
	            enc3 = keyStr.indexOf(input.charAt(i++));
	            enc4 = keyStr.indexOf(input.charAt(i++));

	            chr1 = (enc1 << 2) | (enc2 >> 4);
	            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
	            chr3 = ((enc3 & 3) << 6) | enc4;

	            output = output + String.fromCharCode(chr1);

	            if (enc3 != 64) {
	                output = output + String.fromCharCode(chr2);
	            }
	            if (enc4 != 64) {
	                output = output + String.fromCharCode(chr3);
	            }

	            chr1 = chr2 = chr3 = "";
	            enc1 = enc2 = enc3 = enc4 = "";

	        } while (i < input.length);

	        return unescape(output);
	    }
	})(b64);
	/*
		Ctor: translator.encoding.shift
		
		The implementation of base encoder/decoder, it is based on base64 algorithsm 
	*/
	translator.encodings.base = mapo.ctor(function(){
		translator.encodings.availables.push(this);
	});
	var p = translator.encodings.base.prototype;
	p.prefix = "[ламек";
	p.subfix = "ламек]";
	p.name = "base";
	p._reStartWith = function() {
		return new RegExp("^\\s*.?" + this.prefix.replace("[", "\\["));
	};
	p._reEndWith = function(){
		return new RegExp(this.subfix.replace("[", "\\[") + "\\s*.?$");
	};
	p.encode = function(msg){
		return this.prefix + b64.encode(msg)+ this.subfix;
	};
	p.decode = function(msg){
		var ret = msg.trim().substr(this.prefix.length, msg.length - this.prefix.length);
		ret = ret.substr(0, ret.length - this.subfix.length);
		return b64.decode(ret);
	};
	p.isEncoded = function(msg){
		if (this._reStartWith().test(msg) &&
			this._reEndWith().test(msg)){
			return true;
		}
		return false;
	};
	
	new translator.encodings.base();
})();